#include "mainwindow2.h"
#include "ui_mainwindow2.h"
#include <QDebug>
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>

#include "facedetector.h"
#include "facekeypointdetector.h"
#include <xmmintrin.h>  //sse
#include "noticewidget.h"
#include "opencv_qt_utils.h"
using namespace std;
using namespace cv;

MainWindow2::MainWindow2(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow2)
{
    ui->setupUi(this);


    //创建当天数据库
    cout<<today.toStdString().c_str()<<endl;
    ui->timelable->setText("记录表"+today);

    helper.createTable2(today);
    if(helper.selectAllcount(today)==0)//初始为空的话，进行初始化
    {
        std::vector<QString> names = helper.selectNames(QString("face"));
        for(int i=0;i<names.size();i++){
            helper.insert2(today , names[i],0);//记录表生成
        }
    }


//    firstThread = new QThread;
    myCamThread = new Camerawork;
//    myCamThread->moveToThread(firstThread);

    secondThread = new QThread;
    faceThread = new Facework;
    faceThread->moveToThread(secondThread);

    //摄像1
    //人脸检测 30ms
    connect(&theTimer, SIGNAL(timeout()), this, SLOT(updateImage()));


    //人脸识别 3s
    connect(myCamThread,SIGNAL(sendFace(cv::Mat)),this,SLOT(reciveFace(cv::Mat)));
    connect(faceThread,SIGNAL(sendName(QString)),this,SLOT(reciveFacename(QString)));
    connect(faceThread,SIGNAL(sendName(QString)),this,SLOT(alertShow(QString)));

    //识别到后，触发sql数据插入

    //摄像2----------------------------------------------------------------------------------------
    myCamThread2 = new Camerawork;

    connect(&theTimer2, SIGNAL(timeout()), this, SLOT(updateImage2()));
    //接受人脸保存
    connect(faceThread,SIGNAL(sendFeat(ncnn::Mat)),this,SLOT(reciveFeat(ncnn::Mat)));

    //置信度改变

    ui->zhixindutext->setValidator(new QIntValidator(ui->zhixindutext));

    connect(ui->zhixinduslider, SIGNAL(valueChanged(int)), this, SLOT(setZhixinValue()));

    connect(ui->zhixindutext, SIGNAL(editingFinished()), this, SLOT(setZhixinSliderValue()));

    connect(ui->zhixinduslider, SIGNAL(valueChanged(int)), faceThread, SLOT(getZhixindu(int)));

}



MainWindow2::~MainWindow2()
{
    delete ui;
}




void MainWindow2::reciveFacename(QString name)
{
    cout<<"reciveFacename"<<endl;
    QString path;
    if(name!=QString("not find")){
        QStringList list =  name.split(":");
        QString s = list.at(0);
        path = helper.selectpathbyid(s);
        QImage filepic;
        filepic.load(path);
        filepic = filepic.scaled(ui->lblImage->size());
        ui->lblImage->setPixmap(QPixmap::fromImage(filepic));
    }else{
        ui->lblImage->setText("not find");
    }

    ui->lblStatus->setText(name);
}

void MainWindow2::reciveFace(cv::Mat img)
{
    cout<<"reciveFace"<<endl;
    faceThread->runncnn(img);
}

//---------------------------------------------------------------------------------------------------------页面1


void MainWindow2::updateImage()
{
    if (!capture.isOpened())
        return;
    capture>>image_fliped;
    cv::flip(image_fliped, image_fliped, 1);

    if(image_fliped.data)
    {

        QImage tem = QImage((const unsigned char *)(image_fliped.data), image_fliped.cols,
                            image_fliped.rows, image_fliped.cols * 3, QImage::Format_RGB888).rgbSwapped();

        myCamThread->runFacencnn(image_fliped,tem,faceimage);

        ui->imageLabel->setPixmap(QPixmap::fromImage(tem));

        ui->imageLabel->show();
    }
}

void MainWindow2::updateImage2()
{
    if (!capture.isOpened())
        return;
    capture>>image_fliped;
    cv::flip(image_fliped, image_fliped, 1);

    if(image_fliped.data)
    {

        QImage tem = QImage((const unsigned char *)(image_fliped.data), image_fliped.cols,
                            image_fliped.rows, image_fliped.cols * 3, QImage::Format_RGB888).rgbSwapped();

        myCamThread2->runFacencnn2(image_fliped,tem,faceimage);

        ui->imageLabel_2->setPixmap(QPixmap::fromImage(tem));
        ui->imageLabel_2->show();
    }
}


void MainWindow2::on_btnOpenCam_clicked()
{
    if (capture.isOpened())
        return;

    if (capture.open(200)) {
        cout<<"cam is  opened"<<endl;
//        capture.set(CV_CAP_PROP_FPS, 30);//帧率 帧/秒
        //从摄像头捕获视频
//        firstThread->start();//可启用线程或者不启用
        secondThread->start(QThread::InheritPriority);

        theTimer.start(60);//人脸检测

        theTimer3.start(3000);
    }else {
        cout<<"cam is not opened"<<endl;
        capture.release();
    }
    //打开视频流

}




void MainWindow2::on_btnCloseCam_clicked()
{
    capture.release();

    theTimer.stop();
    theTimer3.stop();
    secondThread->quit();
    secondThread->wait();
}



//置信度
void MainWindow2::setZhixinValue()
{
    int pos = ui->zhixinduslider->value();
    QString str = QString("%1").arg(pos);
    ui->zhixindutext->setText(str);
}

void MainWindow2::setZhixinSliderValue()
{
    int pos = ui->zhixindutext->text().toInt();

    cout<<"pos"+pos<<endl;


    ui->zhixinduslider->setValue(pos);
}



//------------------------------------------------------------------页面2


void MainWindow2::on_fileselect_clicked()
{
    //括号里的参数分别是：指定父类、标题、默认打开后显示的目录、右下角的文件过滤器。

    QString filename = QFileDialog::getOpenFileName(NULL,"",".","*.jpg");

    if(filename!=NULL){
        QImage filepic;

        //显示图片
        filepic.load(filename);
        cv::Mat temface = OpencvQtUtils::toCvMat(filepic);

        qDebug()<<filepic.height()<<"filepic.height";
        if(filepic.height()!=112){//不是标准输入，就人脸检测
            myCamThread->runFacencnn2(temface,filepic,faceimage);
            filepic = filepic.scaled(ui->lblImage_2->size());
            ui->lblImage_2->setPixmap(QPixmap::fromImage(filepic));
            ui->filename->setText(filename);

            faceThread->getFeat(faceimage);
        }else{
            filepic = filepic.scaled(ui->lblImage_2->size());
            ui->lblImage_2->setPixmap(QPixmap::fromImage(filepic));
            ui->filename->setText(filename);
            faceThread->getFeat(temface);
        }
        imagepath = filename;

    }

}


void MainWindow2::on_btnOpenCam_2_clicked()
{
    if (capture.isOpened())
        return;

    if (capture.open(200)) {
        cout<<"cam is  opened"<<endl;
    //capture.set(CV_CAP_PROP_FPS, 30);//帧率 帧/秒

        theTimer2.start(40);//40人脸检测

    }else {
        cout<<"cam is not opened"<<endl;
        capture.release();
    }
    //打开视频流
    //打开摄像头
}

void MainWindow2::on_btnCloseCam_2_clicked()
{
    theTimer2.stop();
    capture.release();
}

//图片预处理，边缘填充黑色
cv::Mat resizeFaceimg(cv::Mat img,Size size){
    int height = img.rows;
    int width = img.cols;
    int longest_edge = max(height,width);
    cout<<"height"<<height<<"width"<<width<<"longest_edge"<<longest_edge<<endl;
    int top = 0;
    int bottom = 0;
    int left = 0;
    int right = 0;

    if(height < longest_edge){
        int height_diff = longest_edge - height;
        top = int(height_diff / 2);
        bottom = height_diff - top;
    }else if(width < longest_edge){
        int width_diff = longest_edge - width;
        left = int(width_diff / 2);
        right = width_diff - left;
    }

    cv::Mat image_with_border;//填充
    cv::Mat resized_image;//大小适应

    //黑色
    cv::copyMakeBorder(img,image_with_border,top,bottom, left, right, cv::BORDER_CONSTANT);
    cv::resize(image_with_border,resized_image, size);

    return resized_image;
}



void MainWindow2::reciveFeat(ncnn::Mat feat)
{
    //接受人脸特征 , 调用数据库保存128
    cout<<"获得特征保存"<<endl;
    facefeat = feat;
}



std::string Convert(float Num)
{
    std::ostringstream oss;
    oss<<Num;
    std::string str(oss.str());
    return str;
}

QString MainWindow2::matToQstring(ncnn::Mat& m){
    QString res;
    string str;
    for (int q=0; q<m.c; q++)
    {
        const float* ptr = m.channel(q);
        for (int y=0; y<m.h; y++)
        {
            for (int x=0; x<m.w; x++)
            {
                if(x!=m.w-1)
                {

                    str+=Convert(ptr[x]);
                    str+=",";
                }
                else
                    str+=Convert(ptr[x]);

            }
            ptr += m.w;
        }
    }
    res = QString::fromStdString(str);

    return res;
}

void MainWindow2::on_btnStartCapture_2_clicked()
{

    char image_path[64] = {0};

    QDateTime time = QDateTime::currentDateTime();
    QString dateStr =time.toString("yyyy-MM-dd");


    //图片大小变换，两侧填充黑色
    cv::Mat temface;

    if(faceimage.cols!=0)
        temface = resizeFaceimg(faceimage,Size(112, 112));
    else
        cout<<"人脸为空"<<endl;

    if (temface.empty())
    {
        std::cout << "frame1 is empty" << std::endl;
        return;
    }else{
        cout<<"index="<< index + 1 <<", temface.size= "<<temface.size<<temface.type()<<endl;
        sprintf(image_path,"%s%s_%d-%d-%d_%d%s","/apps/VideoCaptureQt/pic/", dateStr.toStdString().c_str(),
                            time.time().hour(),time.time().minute(),time.time().second(), index++,".jpg");
        cout<<image_path<<endl;
        //保存图片
        cv::imwrite(image_path, temface);
        sleep(1);
    }

    QImage image((const unsigned char *)(temface.data), temface.cols, temface.rows, temface.step, QImage::Format_RGB888);

    image = image.scaled(ui->lblImage_2->size());

    //显示图片

    ui->lblImage_2->setPixmap(QPixmap::fromImage(image));

    imagepath = QString(image_path);;
    qDebug()<<imagepath;
    ui->filename->setText(imagepath);
    faceThread->getFeat(temface);

}

void MainWindow2::on_pushfile_clicked()
{

    QString featstr = matToQstring(facefeat);
    QString peoplename = ui->filename->text();

    helper.insert(QString("face"),peoplename,featstr,imagepath);
    QString temid = helper.selectfinalid(QString("face"));
    helper.insert2(today , temid+":"+peoplename , 0);//记录表生成

    helper.select(QString("face"));

    static NoticeWidget noticeWin;
    noticeWin.Notice(this, QString("上传成功"), 3000);

}


//菜单栏改变，将线程停止
void MainWindow2::on_tabWidget_currentChanged(int index)
{
    qDebug()<<index;
    if(theTimer.isActive()){
        theTimer.stop();
        capture.release();
        theTimer3.stop();
        secondThread->quit();
        secondThread->wait();
    }
    if(theTimer2.isActive()){
        theTimer2.stop();
        capture.release();
    }
    if(index==2){
        QSqlQueryModel *model=new QSqlQueryModel(ui->tableView);
        model->clear();
        model->setQuery("SELECT * FROM "+today);//提取所有的数据
        model->setHeaderData(0, Qt::Horizontal, tr("ID"));
        model->setHeaderData(1, Qt::Horizontal, tr("姓名"));
        model->setHeaderData(2, Qt::Horizontal, tr("是否签到"));
        ui->tableView->setModel(model);
        ui->tableView->resizeColumnsToContents();//自动根据内容调整列宽
    }

    if(index==3){
        QSqlQueryModel *model2=new QSqlQueryModel(ui->tableView_2);
        model2->clear();
        model2->setQuery("SELECT id,name,imagepath FROM face");//提取所有的数据
        model2->setHeaderData(0, Qt::Horizontal, tr("ID"));
        model2->setHeaderData(1, Qt::Horizontal, tr("姓名"));
        model2->setHeaderData(2, Qt::Horizontal, tr("人脸路径"));
        ui->tableView_2->setModel(model2);
        ui->tableView_2->resizeColumnsToContents();//自动根据内容调整列宽
    }
}


//------------------------------------------------------------------------数据库

//弹出提示，添加数据库
void MainWindow2::alertShow(QString str)
{
    if(str!=QString("not find"))
    {
        static NoticeWidget noticeWin;
        noticeWin.Notice(this, str+QString(" 签到成功！"), 1500);
        helper.updateflag(today,str);
    }else{
        static NoticeWidget noticeWin;
        noticeWin.Notice(this, str+QString("未识别！"), 1500);
    }
    helper.select2(today);
}


void MainWindow2::on_deletefacedata_clicked()
{
    int curRow = ui->tableView_2->currentIndex().row();

    if(curRow==-1)
    {
        static NoticeWidget noticeWin;
        noticeWin.Notice(this, QString("请先选中单元格！！"), 1500);
        return;
    }
    int ok = QMessageBox::warning(this, "删除", "确定删除？", QMessageBox::Yes, QMessageBox::No);

    if (ok == QMessageBox::No) {
        qDebug() << "取消";
        return;
    }
    QSqlQueryModel *model2=new QSqlQueryModel(ui->tableView_2);
    model2->setQuery("SELECT id,name,imagepath FROM face");//提取所有的数据
    model2->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model2->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model2->setHeaderData(2, Qt::Horizontal, tr("人脸路径"));

    int id = model2->data(model2->index(curRow,0)).toInt();

    qDebug()<<curRow;
    QSqlQuery query;
    query.prepare("delete from face where id =:id ");
    query.bindValue("id",id);
    query.exec();
    QSqlQuery query2;
    query2.prepare("delete from "+today+" where id =:id ");
    query2.bindValue("id",id);
    query2.exec();
    if(!query.isActive()&&!query2.isActive()){
        QMessageBox::critical(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("删除数据失败!"));
        return;
    }

    static NoticeWidget noticeWin;
    noticeWin.Notice(this, QString("删除成功"), 1500);

    model2->clear();
    model2->setQuery("SELECT id,name,imagepath FROM face");//提取所有的数据
    model2->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model2->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model2->setHeaderData(2, Qt::Horizontal, tr("人脸路径"));
    ui->tableView_2->setModel(model2);
    ui->tableView_2->resizeColumnsToContents();//自动根据内容调整列宽
}

void MainWindow2::on_notflagbtn_clicked()
{
    helper.select2(today);
    QSqlQueryModel *model=new QSqlQueryModel(ui->tableView);
    model->clear();
    model->setQuery("SELECT * FROM "+today+" where flag=0");//提取所有的数据
    model->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model->setHeaderData(2, Qt::Horizontal, tr("是否签到"));
    ui->tableView->setModel(model);
    ui->tableView->resizeColumnsToContents();//自动根据内容调整列宽
}

void MainWindow2::on_allflagbtn_clicked()
{
    QSqlQueryModel *model=new QSqlQueryModel(ui->tableView);
    model->clear();
    model->setQuery("SELECT * FROM "+today);//提取所有的数据
    model->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model->setHeaderData(2, Qt::Horizontal, tr("是否签到"));
    ui->tableView->setModel(model);
    ui->tableView->resizeColumnsToContents();//自动根据内容调整列宽
}

void MainWindow2::on_okflagbtn_clicked()
{
    QSqlQueryModel *model=new QSqlQueryModel(ui->tableView);
    model->clear();
    model->setQuery("SELECT * FROM "+today+" where flag=1");//提取所有的数据
    model->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model->setHeaderData(2, Qt::Horizontal, tr("是否签到"));
    ui->tableView->setModel(model);
    ui->tableView->resizeColumnsToContents();//自动根据内容调整列宽
}



void MainWindow2::on_updatefacedata_clicked()
{
    int curRow = ui->tableView_2->currentIndex().row();

    if(curRow==-1)
    {
        static NoticeWidget noticeWin;
        noticeWin.Notice(this, QString("请先选中单元格！！"), 1500);
        return;
    }

    QSqlQueryModel *model2=new QSqlQueryModel(ui->tableView_2);
    model2->setQuery("SELECT id,name,imagepath FROM face");//提取所有的数据
    model2->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model2->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model2->setHeaderData(2, Qt::Horizontal, tr("人脸路径"));

    int id = model2->data(model2->index(curRow,0)).toInt();
    QString idstr = model2->data(model2->index(curRow,0)).toString();

    QString name = model2->data(model2->index(curRow,1)).toString();

    QString dlgTitle="修改";
    QString txtLabel="请输入姓名";
    QString defaultInput=name;
    QLineEdit::EchoMode echoMode=QLineEdit::Normal;//正常文字输入
    bool ok=false;
    QString text = QInputDialog::getText(this, dlgTitle,txtLabel, echoMode,defaultInput, &ok);

    if(text!=""){

        QSqlQuery query;
        query.prepare("update face set name = '"+text+"' where id =:id ");
        query.bindValue("id",id);
        query.exec();
        QSqlQuery query2;
        query2.prepare("update "+today+" set name = '"+idstr+":"+text+"' where id =:id ");
        query2.bindValue("id",id);
        query2.exec();
        if(!query.isActive()&&!query2.isActive()){
            QMessageBox::critical(this,QString::fromLocal8Bit("提示"),QString::fromLocal8Bit("修改数据失败!"));
            return;
        }
        static NoticeWidget noticeWin;
        noticeWin.Notice(this, QString("修改成功"), 1500);
        model2->clear();
        model2->setQuery("SELECT id,name,imagepath FROM face");//提取所有的数据
        model2->setHeaderData(0, Qt::Horizontal, tr("ID"));
        model2->setHeaderData(1, Qt::Horizontal, tr("姓名"));
        model2->setHeaderData(2, Qt::Horizontal, tr("人脸路径"));
        ui->tableView_2->setModel(model2);
        ui->tableView_2->resizeColumnsToContents();//自动根据内容调整列宽
    }

}

void MainWindow2::on_lookpic_clicked()
{
    int curRow = ui->tableView_2->currentIndex().row();

    if(curRow==-1)
    {
        static NoticeWidget noticeWin;
        noticeWin.Notice(this, QString("请先选中单元格！！"), 1500);
        return;
    }

    QSqlQueryModel *model2=new QSqlQueryModel(ui->tableView_2);
    model2->setQuery("SELECT id,name,imagepath FROM face");//提取所有的数据
    model2->setHeaderData(0, Qt::Horizontal, tr("ID"));
    model2->setHeaderData(1, Qt::Horizontal, tr("姓名"));
    model2->setHeaderData(2, Qt::Horizontal, tr("人脸路径"));


    QString name = model2->data(model2->index(curRow,1)).toString();

    QString path = model2->data(model2->index(curRow,2)).toString();

    QLabel* labelImage = new QLabel(this, Qt::Dialog |Qt::WindowCloseButtonHint);
    labelImage->setWindowTitle(name);


    QFileInfo file(path);

    if(file.exists())
    {
        QImage image;
        image.load(path);

        /* 下面这两句代码是Label跟随图片大小变化 */
        //ret->resize(QSize(image.width(), image.height()));
        //ret->setPixmap(QPixmap::fromImage(image));

        /* 这两句是图片跟随label大小变化 */
        labelImage->resize(210,210);
        labelImage->setPixmap(QPixmap::fromImage(image.scaled(210, 210, Qt::KeepAspectRatio)));
    }
    else{
        qDebug() << "未找到该图片";
    }
    labelImage->setGeometry(210,210,210,210);
    labelImage->show();
}
